package com.achievo.reportserver;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

import org.apache.log4j.Logger;

import com.achievo.reportserver.config.ConfigFactory;
import com.achievo.reportserver.config.ReportDef;
import com.achievo.reportserver.config.ReportParam;
import com.achievo.reportserver.ds.BeanFactory;
import com.achievo.reportserver.ds.DataSourceFactory;
import com.achievo.reportserver.json.MyDateValueProcessor;
import com.achievo.reportserver.mq.JmsConfig;


/**
 * 
 * Report Server
 * write at Jan 21, 2010
 * @author <a href="mailto:chinaoryx@gmail.com">Hyman.Zhang (Zhang Haipeng)</a>
 * @version 1.0
 * 
 *
 */
public class ReportFacade implements Runnable, ReportConstant {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(ReportFacade.class);
	
	private ReportDef reportDef;
	
	
	public ReportFacade(ReportDef reportDef) {
		super();
		this.reportDef = reportDef;
	}

	public void printReport() throws JRException, SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException, IOException{
		
		String outFileName = null;
		StringBuffer fileName = new StringBuffer(reportDef.getOutFileRealPathRoot());
		fileName.append(reportDef.getOutFileName());
		// the outfile is exist!
		File outFile = new File(fileName.toString());
		if (outFile.exists() && this.reportDef.getExpireTime() != null) {
			long timeLong = outFile.lastModified();
			Date lastModified = new Date(timeLong);
			Date now = new Date();
			long nowLong = now.getTime();
			
			long diffLong = nowLong - timeLong;
			long mintis = diffLong/(1000*60);
			
			if (mintis < this.reportDef.getExpireTime()) {
				return ;
			}
		}
		
		
		// construct the paramMap
		List<ReportParam> paramList = this.reportDef.getParamList();
		Map<String, Object> paramMap = new Hashtable<String, Object>();
		if (paramList != null) {
			for (ReportParam reportParam : paramList) {
				if (reportParam.getParamValue() != null) {
					paramMap.put(reportParam.getParamName(), reportParam.getParamValue());
				}
			}
		}
		
		
		ClassLoader classLoader = this.getClass().getClassLoader();
		String reportTemplateRoot = ConfigFactory.getServerConfig().getString("reportTemplateRoot");
		String reportFile = reportDef.getReportTemplateFile();
		String fileLoc = reportTemplateRoot + File.separator + reportFile;
		URL url = classLoader.getResource(fileLoc);
		
		String reportEngine = reportDef.getReportEngine();		
		JasperReport jasperReport = (JasperReport) JRLoader.loadObject(url);
		String datasource = reportDef.getDatasource();
		String[] datasourceArray = datasource.split(":");		
		JasperPrint print = null;
		if ("conn".equalsIgnoreCase(datasourceArray[0])) {
			Connection jdbcConn = DataSourceFactory.getDataSource(datasourceArray[1]).getConnection();
			print = JasperFillManager.fillReport(jasperReport, paramMap, jdbcConn);
			
		} else if ("bean".equalsIgnoreCase(datasourceArray[0])){
			JRDataSource ds = null;
			String beanFactoryclassname = datasourceArray[1];
			BeanFactory beanFactory = (BeanFactory) Class.forName(beanFactoryclassname).newInstance();
			ds = new JRBeanCollectionDataSource(beanFactory.genBeanList());			
			print = JasperFillManager.fillReport(jasperReport, paramMap, ds);
		}
				
		
		if (TYPE_PDF.equalsIgnoreCase(reportDef.getReportType())) {			
//			FileOutputStream o = new FileOutputStream(fileName.toString());

			JasperExportManager.exportReportToPdfFile(print, fileName.toString());
//			o.close();
			
//			JasperExportManager.exportReportToPdf
		} else if (TYPE_HTML.equalsIgnoreCase(reportDef.getReportType())){			
			JasperExportManager.exportReportToHtmlFile(print, fileName.toString());
		}
		
		logger.info("print report("+reportDef.getReportId()+") OK!");
		
//		reportDef.setOutFileLocation(fileName.toString());
		
		
	}

	public void run() {
		Throwable t = null;
		try {			
			this.printReport();
		} catch (Exception e) {
			logger.error("printReport Error!", e);
			t = e;
		}
		
		String text = null;
		String desc = null;
		if (t == null) {
			text = "OK";
		} else {
			text = "ERROR";
			ReportDomUtils utils = new ReportDomUtils();
			desc = utils.stringThrowable(t);
		}
		
		
		
		javax.jms.Connection conn = JmsConfig.getEmailProducerConn();
		// create javax.jms.Session
    	try {
			Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
			Queue queue = session.createQueue(JmsConfig.QUEUE_EMAIL);
			MessageProducer producer = session.createProducer(queue);      
	    	producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);    	
	    	TextMessage msg = session.createTextMessage(text);	    	
	    	
	    	
	    	JSONObject jsonObj = null;
	    	JsonConfig cfg=new JsonConfig();  
	    	cfg.registerJsonValueProcessor(java.util.Date.class, new MyDateValueProcessor());  
	    	cfg.registerJsonValueProcessor(java.sql.Date.class, new MyDateValueProcessor());  
	    	jsonObj = JSONObject.fromObject(this.reportDef, cfg);
	    	String json = jsonObj.toString();
	    	msg.setStringProperty("json", json);
	    	msg.setStringProperty("desc", desc);
	    	
	    	producer.send(msg);  
		} catch (JMSException e) {
			logger.error("onFileCreate", e);
		}

	}

}
